import re


class PmsWait:
    """自定义元素等待，用于替代page.wait_for_timeout()"""

    @staticmethod
    def wait_list(page: Page, timeout=60000) -> None:
        """等待列表数据加载完成"""
        page.get_by_text(re.compile("^第.*条/总共.*条")).click(timeout=timeout)

    @staticmethod
    def wait_dialog_list(page: Page, name, timeout=60000) -> None:
        """等待弹窗中的列表数据加载完成"""
        page.get_by_role("dialog", name=name).get_by_text(re.compile("^第.*条/总共.*条")).click(timeout=timeout)

    @staticmethod
    def wait_dialog_by_description(page: Page, name="策略说明书历史版本", timeout=60000) -> None:
        """等待策略说明书弹窗打开完成"""
        page.get_by_role("dialog", name=name).get_by_text(name).click(timeout=timeout)

    @staticmethod
    def wait_dialog_close(page: Page, name, timeout=60000) -> None:
        """等待策略说明书弹窗打开完成"""
        page.get_by_role("dialog", name=name).get_by_text(name).wait_for(state="hidden", timeout=timeout)

    @staticmethod
    def wait_text_appear(page: Page, text, exact=True, timeout=60000) -> None:
        """等待基础信息模块加载完成/或其他根据特定文本显示的情况"""
        page.get_by_text(text, exact=exact).first.click(timeout=timeout)

    @staticmethod
    def wait_add_fund(page: Page, timeout=60000) -> None:
        """等待添加基金模块加载完成"""
        page.get_by_role("listitem", name=re.compile(r"^1.*")).click(timeout=timeout)

    @staticmethod
    def wait_risk_monitor(page: Page, timeout=60000) -> None:
        """等待风险监控信息模块加载完成"""
        page.get_by_role("cell", name="现金和其他资产").click(timeout=timeout)

    @staticmethod
    def wait_button_hidden(page: Page, button_name="确 定", exact=True, timeout=60000) -> None:
        """等待某个按钮消失, 用于低频率按钮场景"""
        page.get_by_role("button", name=button_name, exact=exact).wait_for(state="hidden", timeout=timeout)

    @staticmethod
    def wait_button_appear(page: Page, button_name="确 定", exact=True, timeout=60000) -> None:
        """等待某个按钮出现"""
        page.get_by_role("button", name=button_name, exact=exact).wait_for(state="visible", timeout=timeout)

    @staticmethod
    def wait_adjust_setting(page: Page, timeout=60000) -> None:
        """批量调仓-等待跳转到调仓设置页"""
        page.get_by_role("button", name="重新上传").wait_for(state="hidden", timeout=timeout)

    @staticmethod
    def wait_adjust_confirm(page: Page, timeout=60000) -> None:
        """普通调仓-等待跳转到调仓确认页"""
        page.get_by_role("button", name="试 算").wait_for(state="hidden", timeout=timeout)

    @staticmethod
    def wait_signal_confirm(page: Page, timeout=60000) -> None:
        """普通发车-等待跳转到发车确认页"""
        page.get_by_role("button", name="import 导入转入指令").wait_for(state="hidden", timeout=timeout)

    @staticmethod
    def wait_adjust_complete(page: Page, po_type=None, timeout=60000) -> None:
        """等待提交调仓完成"""
        text = "确定调仓吗？"
        if po_type == Global.configuration:
            page.get_by_role("button", name="返 回").wait_for(state="hidden", timeout=timeout)
            return
        if po_type == Global.signal:
            text = "确定发车吗？"
        page.get_by_text(text).wait_for(state="hidden", timeout=timeout)

    @staticmethod
    def wait_import_curve(page: Page, timeout=60000) -> None:
        """等待目标日期组合调仓页组合成分比例模块加载完成"""
        expect(page.get_by_role("button", name="导入下滑曲线持仓")).to_be_visible(timeout=timeout)

    @staticmethod
    def wait_text_hidden(page: Page, text, exact=True, timeout=60000) -> None:
        """等待特定文本隐藏"""
        page.get_by_text(text, exact=exact).wait_for(state="hidden", timeout=timeout)

    @staticmethod
    def wait_role_editable(page: Page, name, exact=True, timeout=60000) -> None:
        """等待role元素可编辑，当同个页面有多个分页模块时，wait_list不可用，可以用该方法替代"""
        page.get_by_role("cell", name=name, exact=exact).click(timeout=timeout)

    @staticmethod
    def wait_buy_order_list(page: Page, timeout=60000) -> None:
        """等待转入指令列表加载完成"""
        page.get_by_role("cell", name="晨星MPRS评分（新转入资产） info-circle").get_by_text("晨星MPRS评分（新转入资产）").click(
            timeout=timeout)

    @staticmethod
    def wait_adjust_list(page: Page, timeout=60000) -> None:
        """等待调仓页设置持仓比例列表加载完成"""
        page.get_by_role("cell", name="总计").click(timeout=timeout)

    @staticmethod
    def wait_dialog_list_by_role(page: Page, dialog_name, timeout=60000) -> None:
        """等待调仓页设置持仓比例列表加载完成"""
        page.get_by_role("dialog", name=dialog_name).get_by_role("cell", name="总计").click(timeout=timeout)

    @staticmethod
    def wait_field_hidden(page: Page, field_name="策略名称",timeout=60000) -> None:
        """等待输入框隐藏"""
        page.get_by_label(field_name).wait_for(state="hidden", timeout=timeout)

    @staticmethod
    def _wait_for_response(page: Page, url_pattern: str, timeout: int = 30000) -> Optional[dict]:
        """
        等待并返回与给定URL模式匹配且状态码为200的响应。
        """
        logger.info(f"等待响应: {url_pattern}, 超时: {timeout}ms")
        pattern = re.compile(url_pattern)
        try:
            # 等待符合条件（URL匹配且状态200）的响应事件
            response = page.wait_for_event(
                'response',
                lambda r: pattern.search(r.url) and r.status == 200,
                timeout=timeout
            )
            logger.info(f"捕获到响应: {response.url}")
            return response.json()
        except TimeoutError:
            logger.warning(f"等待 {url_pattern} 响应超时")
            return None

    @classmethod
    def wait_response_200(cls, page: Page, url_pattern: str, timeout: int = 120000) -> bool:
        """
        检查在指定的超时时间内，是否有目标接口响应为 200。
        """
        response_data = cls._wait_for_response(page, url_pattern, timeout)
        return response_data is not None

    @classmethod
    def wait_response_body(cls, page: Page, url_pattern: str, timeout: int = 30000) -> Optional[dict]:
        """
        检查在指定的超时时间内，是否有目标接口返回数据。
        """
        return cls._wait_for_response(page, url_pattern, timeout)

    @staticmethod
    def wait_page_finished_by_url(page: Page) -> bool:
        """
        追踪页面发起的所有请求，判断是否有响应
        :param page: 当前页面实例
        :return: 如果所有请求都有响应则返回True，否则返回False
        """
        all_requests = []
        all_response = []
        temp_list = []
        # 监听所有发起的请求
        page.on("request", lambda request: all_requests.append(request.url))
        # 监听所有成功完成的请求
        page.on("requestfinished", lambda request: all_response.append(request.url))
        # 等待页面加载完成
        page.wait_for_load_state("networkidle")
        logger.info("all_requests: %s" % all_requests)
        logger.info("all_response: %s" % all_response)
        for requests in all_requests:
            if requests in all_response:
                temp_list.append(requests)

        # 检查是否所有请求都有响应
        return len(all_requests) == len(temp_list)